#include "cli_api.h"
#include "net_cmds.h"
#include "lwip/tcpip.h"
#include "lwip/netif.h"

extern uint8_t g_mac_addr[6];
extern struct netif loop_netif;
extern err_t ethernetif_init(struct netif *netif);

static void net_command_usage(const char *prog)
{
    printf("  Usage: %s [OPTIONS]\r\n", prog);
    printf("  Options:\r\n");
    printf("  get mac                                    Get mac address\r\n");
    printf("  set mac                                    Set mac address(e.g.: x x x x x x)\r\n");
    printf("  del mac                                    Del mac address\r\n");

    printf("\r\n");
}

static void _print_mac(uint8_t mac[6])
{
    char macstr[32] = {0};

    for(int i = 0; i < MAC_LEN; i++) {
    sprintf(macstr, "%02x-%02x-%02x-%02x-%02x-%02x", 
        mac[0], mac[1], mac[2], 
        mac[3], mac[4], mac[5]);   
    }

    printf("mac :\n");
    printf("%s\n", macstr);
}

static void get_net_mac(uint8_t mac[6])
{   
    _print_mac(mac);
}

int get_net_mac_kv(uint8_t mac[6])
{   
    int32_t ret;
    int32_t len = MAC_LEN;

    ret = aos_kv_get(NET_MAC_IN_KV, mac, &len);

    return ret;
}

static int del_net_mac(void)
{   
    int32_t ret;
    int32_t len = MAC_LEN;

    ret = aos_kv_del(NET_MAC_IN_KV);
    if (ret == 0) {
        cli_printf("mac del success.\r\n");
    } else {
        cli_printf("mac del fail\r\n");
    }

    return ret;
}

static void _mac_update(uint8_t mac[6])
{
    memset(g_mac_addr, 0, MAC_LEN);
    memcpy(g_mac_addr, mac, MAC_LEN);
}

static int mac_str_to_bin( char *str, unsigned char *mac)
{
    int i;
    char *s, *e;

    if ((mac == NULL) || (str == NULL))
    {
        return -1;
    }

    s = (char *) str;
    for (i = 0; i < MAC_LEN; ++i) {
        mac[i] = s ? strtoul (s, &e, 16) : 0;
        if (s)
           s = (*e) ? e + 1 : e;
    }
    
    return 0;
}

int mac_update(char *macstr)
{
    int ret = 0;
    uint8_t mac[8] = {0};

    ret = mac_str_to_bin(macstr, mac);
    if (ret < 0) {
        return -1;
    }
    ret = aos_kv_set(NET_MAC_IN_KV, mac, MAC_LEN, 1);
    if (ret == 0) {
        cli_printf("mac set success.\r\n");
        _mac_update(mac);
        _print_mac(g_mac_addr);
        netif_remove(&loop_netif);
        netif_init();
    } else {
        cli_printf("mac set fail\r\n");
    }

    return ret;
}


static int set_net_mac(int argc, char **argv)
{
    int i = 0;
    int32_t ret = 0;

    if (argc < 4) {
        printf("param invalid\n");
    }

    return mac_update(argv[3]);    
}


static int get_net_para(int argc, char **argv)
{
    uint32_t ret = 0;

    if (!strcmp(argv[2], "mac")) {
        get_net_mac(g_mac_addr);
    } else {
        printf("param invalid!\n");
        ret = -1;
    }

    return ret;
}

static int set_net_para(int argc, char **argv)
{
    uint32_t ret = 0;

    if (!strcmp(argv[2], "mac")) {
        set_net_mac(argc, argv);
    } else {
        printf("param invalid!\n");
        ret = -1;
    }

    return ret;
}

static int del_net_para(int argc, char **argv)
{
    uint32_t ret = 0;

    if (!strcmp(argv[2], "mac")) {
        del_net_mac();
    } else {
        printf("param invalid!\n");
        ret = -1;
    }

    return ret;
}

void net_command(char *outbuf, int len, int argc, char **argv)
{
    if (argc == 1) {
        net_command_usage(argv[0]);
        return;
    }
    if (!strcmp(argv[1], "get")) {
        get_net_para(argc, argv);
    } else if (!strcmp(argv[1], "set")) {
        set_net_para(argc, argv);
    } else if (!strcmp(argv[1], "del")) {
        del_net_para(argc, argv);
    } else {
       printf("param invalid!\n");
    }

    return;
}

static const struct cli_command_st net_cli_cmd[] = 
{
    [0] =
    {
        .name            = "net",
        .help            = "net [set|get <mac>]",
        .function        = net_command
    },
};

int net_cmds_cli_register(void) 
{
    int ret = 0;

    ret = cli_register_commands(net_cli_cmd, sizeof(net_cli_cmd)/sizeof(struct cli_command_st));
    if (ret != CLI_OK) {
        printf("net cli register fail\n");
        return ret;
    }

    return CLI_OK;
}